From dea8d7a3007bd4f7fb69d1cf1bb2b9657ab2bcb1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Tue, 29 Aug 2017 11:51:17 +0200 Subject: [PATCH] babl: on demand clone sRGB conversions When a new RGB space is encountered clone all sRGB space to sRGB space conversions, under the assumption that they are implemented respecting/using the customizable TRCs of babl. --- babl/babl-conversion.c | 39 ++++++--- babl/babl-fish-path.c | 187 +++++++++++++++++++++++++++++++++++++---- babl/babl-fish.c | 8 +- babl/babl-format.c | 7 +- babl/babl-internal.h | 7 ++ babl/babl-list.c | 2 +- 6 files changed, 213 insertions(+), 37 deletions(-) diff --git a/babl/babl-conversion.c b/babl/babl-conversion.c index 3968504..14567e1 100644 --- a/babl/babl-conversion.c +++ b/babl/babl-conversion.c @@ -177,6 +177,29 @@ create_name (Babl *source, Babl *destination, int type) } return buf; } +const char * +babl_conversion_create_name (Babl *source, Babl *destination, int type); + +const char * +babl_conversion_create_name (Babl *source, Babl *destination, int type) +{ + Babl *babl; + char *name; + int id = 0; + collisions = 0; + name = create_name (source, destination, type); + babl = babl_db_exist (db, id, name); + while (babl) + { + /* we allow multiple conversions to be registered per extender, each + of them ending up with their own unique name + */ + collisions++; + name = create_name (source, destination, type); + babl = babl_db_exist (db, id, name); + } + return name; +} const Babl * babl_conversion_new (const void *first_arg, @@ -273,19 +296,7 @@ babl_conversion_new (const void *first_arg, type = BABL_CONVERSION_PLANAR; } - collisions = 0; - name = create_name (source, destination, type); - - babl = babl_db_exist (db, id, name); - while (babl) - { - /* we allow multiple conversions to be registered per extender, each - of them ending up with their own unique name - */ - collisions++; - name = create_name (source, destination, type); - babl = babl_db_exist (db, id, name); - } + name = (void*) babl_conversion_create_name (source, destination, type); babl = _conversion_new (name, id, source, destination, linear, plane, planar, user_data); @@ -505,7 +516,7 @@ babl_conversion_error (BablConversion *conversion) fmt_source->class_type == BABL_FORMAT && fmt_destination->class_type == BABL_FORMAT)) { - conversion->error = 0.000042; + conversion->error = 0.0000042; } source = babl_calloc (test_pixels, fmt_source->format.bytes_per_pixel); diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c index 60b2fbe..df5f3e6 100644 --- a/babl/babl-fish-path.c +++ b/babl/babl-fish-path.c @@ -202,7 +202,7 @@ get_conversion_path (PathContext *pc, get_path_instrumentation (&fpi, pc->current_path, &path_cost, &ref_cost, &path_error); if(debug_conversions && current_length == 1) - fprintf (stderr, "%s error:%f cost:%f \n", + fprintf (stderr, "%s error:%f cost:%f \n", babl_get_name (pc->current_path->items[0]), /*babl_get_name (pc->fish_path->fish.source), babl_get_name (pc->fish_path->fish.destination),*/ @@ -227,7 +227,7 @@ get_conversion_path (PathContext *pc, else { /* - * Bummer, we have to search deeper... + * we have to search deeper... */ BablList *list; int i; @@ -265,8 +265,8 @@ _babl_fish_create_name (char *buf, int is_reference) { /* fish names are intentionally kept short */ - snprintf (buf, BABL_MAX_NAME_LEN, "%s %p %p", "", - source, destination); + snprintf (buf, BABL_MAX_NAME_LEN, "%s %p %p %i", "", + source, destination, is_reference); return buf; } @@ -283,11 +283,143 @@ _babl_fish_path_destroy (void *data) return 0; } +BablList *accum = NULL; + +static int +show_item (Babl *babl, + void *user_data) +{ + BablConversion *conv = (void *)babl; + //BablSpace *space = user_data; + + if (conv->destination->class_type == BABL_FORMAT) + { + fprintf (stderr, "%s : %.9f\n", babl_get_name (babl), babl_conversion_error(conv)); + } + + return 0; +} + + +static int +show_fmt (Babl *babl, + void *user_data) +{ + BablConversion *conv = (void *)babl; + + fprintf (stderr, "[[%s\n", babl_get_name (babl)); + + return 0; +} + + +static int +alias_conversion (Babl *babl, + void *user_data) +{ + BablConversion *conv = (void *)babl; + BablSpace *space = user_data; + + if ((conv->source->class_type == BABL_FORMAT) && + (conv->destination->class_type == BABL_FORMAT)) + { + if ((conv->source->format.space == (void*)babl_space ("sRGB")) && + (conv->destination->format.space == babl_space ("sRGB"))) + { + Babl *foo; + switch (conv->instance.class_type) + { + case BABL_CONVERSION_LINEAR: + foo= babl_conversion_new ( + babl_format_with_space ( + (void*)conv->source->instance.name, (void*)space), + babl_format_with_space ( + (void*)conv->destination->instance.name, (void*)space), + "linear", conv->function.linear, + "data", conv->data, + NULL); + break; + case BABL_CONVERSION_PLANAR: + foo= babl_conversion_new ( + babl_format_with_space ( + (void*)conv->source->instance.name, (void*)space), + babl_format_with_space ( + (void*)conv->destination->instance.name, (void*)space), + "planar", conv->function.planar, + "data", conv->data, + NULL); + break; + case BABL_CONVERSION_PLANE: + babl_conversion_new ( + babl_format_with_space ( + (void*)conv->source->instance.name, (void*)space), + babl_format_with_space ( + (void*)conv->destination->instance.name, (void*)space), + "plane", conv->function.plane, + "data", conv->data, + NULL); + break; + default: + break; + } + if(0)fprintf (stderr, "{%s}\n", babl_get_name (foo)); + } + } + else + if ((conv->source->class_type == BABL_MODEL) && + (conv->destination->class_type == BABL_MODEL)) + { + if ((conv->source->model.space == (void*)babl_space ("sRGB")) && + (conv->destination->model.space == babl_space ("sRGB"))) + { + switch (conv->instance.class_type) + { + case BABL_CONVERSION_LINEAR: + babl_conversion_new ( + babl_remodel_with_space ( + (void*)conv->source, (void*)space), + babl_remodel_with_space ( + (void*)conv->destination, (void*)space), + "linear", conv->function, + NULL); + break; + case BABL_CONVERSION_PLANAR: + babl_conversion_new ( + babl_remodel_with_space ( + (void*)conv->source, (void*)space), + babl_remodel_with_space ( + (void*)conv->destination, (void*)space), + "planar", conv->function, + NULL); + break; + case BABL_CONVERSION_PLANE: + babl_conversion_new ( + babl_remodel_with_space ( + (void*)conv->source, (void*)space), + babl_remodel_with_space ( + (void*)conv->destination, (void*)space), + "plane", conv->function, + NULL); + break; + default: + break; + } + } + } + else + if ((conv->source->class_type == BABL_TYPE) && + (conv->destination->class_type == BABL_TYPE)) + { + } + return 0; +} + Babl * babl_fish_path (const Babl *source, const Babl *destination) { Babl *babl = NULL; + const Babl *sRGB = babl_space ("sRGB"); char name[BABL_MAX_NAME_LEN]; _babl_fish_create_name (name, source, destination, 1); @@ -302,6 +434,39 @@ babl_fish_path (const Babl *source, return babl; } + if ((source->format.space != sRGB) || + (destination->format.space != sRGB)) + { + static const Babl *run_once[512]={NULL}; + int i; + int done = 0; + for (i = 0; run_once[i]; i++) + { + if (run_once[i] == source->format.space) + done |= 1; + else if (run_once[i] == destination->format.space) + done |= 2; + } + + if ((done & 1) == 0 && (source->format.space != sRGB)) + { + run_once[i++] = source->format.space; + babl_conversion_class_for_each (alias_conversion, (void*)source->format.space); + } + if ((done & 2) == 0 && (destination->format.space != source->format.space) && (destination->format.space != sRGB)) + { + run_once[i++] = destination->format.space; + babl_conversion_class_for_each (alias_conversion, (void*)destination->format.space); + } + + if (!done) + { + //babl_conversion_class_for_each (show_item, (void*)source->format.space); + //babl_format_class_for_each (show_fmt, NULL); + //babl_model_class_for_each (show_fmt, NULL); + } + } + babl = babl_calloc (1, sizeof (BablFishPath) + strlen (name) + 1); babl_set_destructor (babl, _babl_fish_path_destroy); @@ -543,9 +708,6 @@ process_conversion_path (BablList *path, temp_buffer2 = align_16 (alloca (MIN(n, MAX_BUFFER_SIZE) * sizeof (double) * 5 + 16)); } - - - for (j = 0; j < n; j+= MAX_BUFFER_SIZE) { long c = MIN (n - j, MAX_BUFFER_SIZE); @@ -602,6 +764,7 @@ init_path_instrumentation (FishPathInstrumentation *fpi, { fpi->fmt_rgba_double = babl_format_new ( babl_model ("RGBA"), + babl_space ("sRGB"), babl_type ("double"), babl_component ("R"), babl_component ("G"), @@ -727,15 +890,5 @@ get_path_instrumentation (FishPathInstrumentation *fpi, fpi->ref_destination_rgba_double, fpi->num_test_pixels * 4); -#if 0 - fpi->fish_rgba_to_source->fish.processings--; - fpi->fish_reference->fish.processings--; - fpi->fish_destination_to_rgba->fish.processings -= 2; - - fpi->fish_rgba_to_source->fish.pixels -= fpi->num_test_pixels; - fpi->fish_reference->fish.pixels -= fpi->num_test_pixels; - fpi->fish_destination_to_rgba->fish.pixels -= 2 * fpi->num_test_pixels; -#endif - *ref_cost = fpi->reference_cost; } diff --git a/babl/babl-fish.c b/babl/babl-fish.c index 4cc4924..587c549 100644 --- a/babl/babl-fish.c +++ b/babl/babl-fish.c @@ -169,9 +169,9 @@ babl_fish_get_id (const Babl *source, /* value of 'id' will be used as argument for hash function, * substraction serves as simple combination of * source/destination values. */ - ptrdiff_t id = source - destination; + int id = (((int)source * 93)) ^ ((int)destination); /* instances with id 0 won't be inserted into database */ - id *= ((((size_t) (source))) % 37); + id *= ((((size_t) (destination))) % 37); if (id == 0) id = 1; @@ -254,12 +254,12 @@ babl_fish (const void *source, * path. */ babl_hash_table_find (id_htable, hashval, find_fish_path, (void *) &ffish); - if (ffish.fish_path) { /* we have found suitable fish path in the database */ return ffish.fish_path; } + if (!ffish.fish_fish) { /* we haven't tried to search for suitable path yet */ @@ -269,6 +269,7 @@ babl_fish (const void *source, { return fish_path; } +#if 1 else { /* there isn't a suitable path for requested formats, @@ -287,6 +288,7 @@ babl_fish (const void *source, fish->fish.destination = destination_format; babl_db_insert (babl_fish_db (), fish); } +#endif } } diff --git a/babl/babl-format.c b/babl/babl-format.c index 0afba64..ebf51db 100644 --- a/babl/babl-format.c +++ b/babl/babl-format.c @@ -130,13 +130,16 @@ format_new (const char *name, return babl; } -static Babl * +Babl * format_new_from_format_with_space (const Babl *format, const Babl *space) { Babl *ret; char new_name[256]; sprintf (new_name, "%s-%s", babl_get_name ((void*)format), babl_get_name ((void*)space)); + ret = babl_db_find (babl_format_db(), new_name); + if (ret) + return ret; ret = format_new (new_name, 0, @@ -726,7 +729,7 @@ babl_format_with_space (const char *name, const Babl *space) { char *new_name = babl_malloc (strlen (name) + - strlen (babl_get_name ((Babl*)space)) + 1); + strlen (babl_get_name ((Babl*)space)) + 2); sprintf (new_name, "%s-%s", name, babl_get_name ((Babl*)space)); ret = babl_db_exist_by_name (db, new_name); diff --git a/babl/babl-internal.h b/babl/babl-internal.h index e50fd91..b5a7532 100644 --- a/babl/babl-internal.h +++ b/babl/babl-internal.h @@ -389,5 +389,12 @@ const Babl *babl_space_from_icc (const char *icc, const Babl *babl_trc_lut_find (float *lut, int lut_size); const Babl * babl_trc_lut (const char *name, int n, float *entries); +Babl * +format_new_from_format_with_space (const Babl *format, const Babl *space); +int +babl_list_destroy (void *data); + +const char * +babl_conversion_create_name (Babl *source, Babl *destination, int is_reference); #endif diff --git a/babl/babl-list.c b/babl/babl-list.c index 49647bb..beb7b61 100644 --- a/babl/babl-list.c +++ b/babl/babl-list.c @@ -31,7 +31,7 @@ babl_list_init (void) return babl_list_init_with_size (BABL_LIST_INITIAL_SIZE); } -static int +int babl_list_destroy (void *data) { BablList *list = data; -- 2.30.2